﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace ExcelFileQueryTool
{
    public sealed class ExcelWorkLogGrid : DataGridView
    {
        private static readonly Color PaidOffColor = Color.FromArgb(255, 192, 0);

        private ToolBar _toolbar = new ToolBar();
        private Control _lastParent = null;

        private string[] _cols_hidden;
        private string _col_mark;

        private const String COL_TYPE_NAME = "类型";
        private const String COL_CLIENT_NAME = "客户供应商";

        private static string[] SHIPPING_METHODS_REQUIRE_FEE = new string[] { "三轮", "摩托", "手拖" };

        public ExcelWorkLogGrid()
            : this(null, null)
        { }

        public ExcelWorkLogGrid(string[] hiddenColumns = null, string markColumn = null)
        {
            _cols_hidden = hiddenColumns;

            if (string.IsNullOrEmpty(markColumn))
                _col_mark = COL_CLIENT_NAME;
            else
                _col_mark = markColumn;

            this.AllowUserToAddRows = false;
            this.AllowUserToDeleteRows = false;
            this.AllowUserToOrderColumns = true;
            this.AllowUserToResizeRows = false;
            this.ReadOnly = true;
            this.RowHeadersVisible = false;
            this.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
            this.ShowEditingIcon = false;
            this.MultiSelect = true;
            this.DoubleBuffered = true;
            //this.VirtualMode = true;

            this.BackgroundColor = Color.White;
            this.GridColor = Color.Crimson;
        }

        #region Statistics

        private int _countRecorded = 0;
        private int _countTodo = 0;
        private int _countDisplayed = 0;
        private int _countHidden = 0;

        private int _countSelected = 0;
        private decimal _sumSelected = 0;

        /// <summary>
        /// 是否显示已落数的记录
        /// </summary>
        public bool ShowRecorded { get { return _toolbar.Buttons["btnShowRecorded"].Pushed; } }

        private void UpdateDataStaisticsText()
        {
            if (this.DesignMode)
                return;

            var text = String.Format("[数据统计：未落数 {0}，已落数 {1}，已显示 {2}，已隐藏 {3}，已选 {4}，已选总额 {5}]",
                                    _countTodo, _countRecorded, _countDisplayed, _countHidden, _countSelected, _sumSelected);

            _toolbar.Buttons[_toolbar.Buttons.IndexOfKey("btnStatistics")].Text = text;
        }

        #endregion

        /// <summary>
        /// 刷新行可见性
        /// </summary>
        public void RefreshVisibilityByRecordedStatus()
        {
            if (this.DataSource == null || this.BindingContext == null)
                return;

            var showRecorded = _toolbar.Buttons["btnShowRecorded"].Pushed;
            _toolbar.Buttons["btnShowRecorded"].Text = showRecorded ? "已显示落数记录" : "已隐藏落数记录";

            var manager = (CurrencyManager)this.BindingContext[this.DataSource];
            manager.SuspendBinding();
            this.SuspendLayout();
            this.SuspendDrawing();

            foreach (DataGridViewRow row in this.Rows)
            {
                if (row.Visible == showRecorded)
                    continue;

                if (((ExcelWorkLogItem)row.DataBoundItem).HasRecordOnBook)
                    row.Visible = showRecorded;
            }


            this.ResumeDrawing();
            this.ResumeLayout();
            manager.ResumeBinding();
        }

        protected override void OnParentChanged(EventArgs e)
        {
            if (this.Parent != null && !DesignMode && !this.Parent.Controls.Contains(_toolbar))
            {
                _toolbar.Buttons.Add(new ToolBarButton { Name = "btnShowRecorded", Text = "已隐藏落数记录", Style = ToolBarButtonStyle.ToggleButton });
                _toolbar.Buttons.Add(new ToolBarButton { Name = "btnCurrentFontSize", Text = "当前字体大小：" + this.FontHeight });
                _toolbar.Buttons.Add(new ToolBarButton { Name = "btnShrinkFont", Text = "<缩小字体>" });
                _toolbar.Buttons.Add(new ToolBarButton { Name = "btnEnlargeFont", Text = "<增大字体>" });
                _toolbar.Buttons.Add(new ToolBarButton { Name = "btnStatistics" });

                _toolbar.ButtonClick += toolbar_ButtonClick;

                this.Parent.Controls.Add(_toolbar);
            }

            if (this.Parent == null)
            {
                _lastParent.Controls.Remove(_toolbar);
            }

            _lastParent = this.Parent;

            base.OnParentChanged(e);
        }

        public void toolbar_ButtonClick(object sender, ToolBarButtonClickEventArgs e)
        {
            switch (e.Button.Name)
            {
                case "btnShrinkFont":
                    this.Font = new Font(this.Font.FontFamily, this.Font.Size - 1, FontStyle.Regular);
                    break;

                case "btnEnlargeFont":
                    this.Font = new Font(this.Font.FontFamily, this.Font.Size + 1, FontStyle.Regular);
                    break;

                case "btnShowRecorded":
                    RefreshVisibilityByRecordedStatus();
                    break;

                default:
                    break;
            }

            _toolbar.Buttons[_toolbar.Buttons.IndexOfKey("btnCurrentFontSize")].Text = "当前字体大小：" + this.FontHeight;
        }

        protected override void OnRowPrePaint(DataGridViewRowPrePaintEventArgs e)
        {
            var row = this.Rows[e.RowIndex];
            var rowObj = (ExcelWorkLogItem)row.DataBoundItem;

            if (rowObj.IsPaidOff)
                row.Cells[COL_TYPE_NAME].Style.BackColor = PaidOffColor;

            if (rowObj.HasRecordOnBook)
                row.Cells[_col_mark].Style.BackColor = Color.LightGreen;

            var doesShippingFeeNeedAttention = false;
            var isReturn = (rowObj.类型 == "退货");
            if (isReturn)
            {
                row.Cells[COL_TYPE_NAME].Style.BackColor = Color.Red;
                row.Cells[COL_TYPE_NAME].Style.ForeColor = Color.White;

                // 一般退货的运费都是负数的，如果是正数就需要注意是否填错了
                doesShippingFeeNeedAttention = rowObj.运装卸费 > 0;
            }

            // 判断是否漏写运费，此判定非绝对结果，只是作为提醒让用户尽可能发现漏写的运费
            if (doesShippingFeeNeedAttention == false && string.IsNullOrEmpty(rowObj.运输方式) == false)
                doesShippingFeeNeedAttention = SHIPPING_METHODS_REQUIRE_FEE.Any(x => rowObj.运输方式.Contains(x)) && rowObj.运装卸费 == 0;

            if (doesShippingFeeNeedAttention)
                row.Cells["运装卸费"].Style.BackColor = Color.Yellow;

            base.OnRowPrePaint(e);
        }

        /// <summary>
        /// 每次更新了记录状态，都会执行绘制动作，所以使用绘制事件可以避免多余的统计数更新操作，并且统一了处理切入点，不需要处理各种状态变换
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            var data = (IEnumerable<ExcelWorkLogItem>)this.DataSource;

            if (data != null)
            {
                var total = data.Count();
                var show_recorded = _toolbar.Buttons["btnShowRecorded"].Pushed;

                //_countDisplayed = data.Count(x => x.HasRecordOnBook == false || show_recorded);
                //_countHidden = total - _countDisplayed;
                _countDisplayed = this.Rows.GetRowCount(DataGridViewElementStates.Visible);
                _countHidden = total - _countDisplayed;
                _countRecorded = data.Count(x => x.HasRecordOnBook);
                _countTodo = total - _countRecorded;

                _countSelected = this.SelectedRows.Count;
                _sumSelected = 0;

                foreach (DataGridViewRow row in this.SelectedRows)
                {
                    if (row.Visible)
                        _sumSelected += ((ExcelWorkLogItem)row.DataBoundItem).货款合计;
                    else
                        _countSelected--;
                }
            }
            else
            {
                _countDisplayed = 0;
                _countHidden = 0;
                _countRecorded = 0;
                _countTodo = 0;
                _countSelected = 0;
                _sumSelected = 0;
            }

            UpdateDataStaisticsText();
        }

        //protected override void OnSorted(EventArgs e)
        //{
        //    base.OnSorted(e);
        //    RefreshRecordedLogVisibility();
        //}

        private Control GetTopContainer()
        {
            Control container = this;
            bool isTop = false;

            while (isTop == false)
            {
                if (container.Parent == null)
                    isTop = true;
                else
                    container = container.Parent;
            }

            return container;
        }

        protected override void OnDataBindingComplete(DataGridViewBindingCompleteEventArgs e)
        {
            base.OnDataBindingComplete(e);

            RefreshVisibilityByRecordedStatus(); // must be ahead

            if (_cols_hidden != null)
            {
                foreach (var col in _cols_hidden)
                {
                    if (this.Columns.Contains(col))
                        this.Columns[col].Visible = false;
                }
            }

            this.Columns["SheetName"].Visible = false;
            this.Columns["RowIndex"].Visible = false;
            this.Columns["IsPaidOff"].Visible = false;
            this.Columns["HasRecordOnBook"].Visible = false;

            this.Columns["客户供应商"].HeaderText = "客户/供应商";
            this.Columns["运装卸费"].HeaderText = "运/装/卸费(元)";
            this.Columns["货款合计"].HeaderText = "货款合计(元)";
            this.Columns["已收付货款"].HeaderText = "已收/付货款(元)";
            this.Columns["收付款人"].HeaderText = "收/付款人";
        }
    }
}
